home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / clients / editres / comm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-12  |  22.5 KB  |  851 lines

  1. /* $XConsortium: comm.c,v 1.19 91/04/04 21:35:16 gildea Exp $ */
  2. /*
  3.  * Copyright 1990 Massachusetts Institute of Technology
  4.  * 
  5.  * Permission to use, copy, modify, distribute, and sell this software and its
  6.  * documentation for any purpose is hereby granted without fee, provided that
  7.  * the above copyright notice appear in all copies and that both that
  8.  * copyright notice and this permission notice appear in supporting
  9.  * documentation, and that the name of M.I.T. not be used in advertising or
  10.  * publicity pertaining to distribution of the software without specific,
  11.  * written prior permission.  M.I.T. makes no representations about the
  12.  * suitability of this software for any purpose.  It is provided "as is"
  13.  * without express or implied warranty.
  14.  */
  15.  
  16. /*
  17.  * This file contains the code to communicate with the client that is
  18.  * being edited.
  19.  */
  20.  
  21. #ifdef MSDOS
  22. #include "X11/Intrinsc.h"      /* QDK 05/11/1994 12:54pm. */
  23. #else
  24. #include "X11/Intrinsic.h"
  25. #endif
  26. #include <X11/StringDefs.h>    /* Get standard string definitions. */
  27. #include <X11/Xatom.h>
  28. #include <X11/cursorfont.h>    /* For crosshair cursor. */
  29. #include <X11/Xproto.h>
  30. #include <X11/Xos.h>        /* for XtNewString */
  31.  
  32. #include <stdio.h>
  33. #include <X11/Xmu/Error.h>
  34.  
  35. #include "editresP.h"
  36.  
  37. /*
  38.  * static Globals.
  39.  */
  40.  
  41. static Atom atom_comm, atom_command, atom_resource_editor, atom_client_value;
  42. static Atom atom_editres_protocol;
  43.  
  44. /*
  45.  * external function definitions.
  46.  */
  47.  
  48. extern ResIdent GetNewIdent();
  49. extern void SetMessage(), BuildVisualTree(),DisplayChild();
  50. extern char * GetFormattedSetValuesError(), *HandleFlashWidget();
  51. extern char * HandleGetResources(),  *PrintSetValuesError();
  52. char * GetFailureMessage(), * ProtocolFailure();
  53. extern int HandleXErrors();
  54.  
  55. static void TellUserAboutMessage(), BuildHeader(), FreeEvent();
  56. static Event * BuildEvent();
  57. static char * DispatchEvent();
  58. static void GetClientValue();
  59. static void ClientTimedOut(), LoseSelection(), SelectionDone();
  60. static Boolean ConvertCommand();
  61.  
  62.  
  63. /*    Function Name: ClientTimedOut
  64.  *    Description: Called if the client takes too long to take our selection.
  65.  *    Arguments: data - The widget that owns the client 
  66.  *                        communication selection.
  67.  *                 id - *** UNUSED ***
  68.  *    Returns: none.
  69.  */
  70.  
  71. /* ARGSUSED */
  72. static void
  73. ClientTimedOut(data, id)
  74. XtPointer data;
  75. XtIntervalId * id;
  76. {
  77.     char msg[BUFSIZ];
  78.     Widget w = (Widget) data;
  79.     
  80.     global_client.ident = NO_IDENT;
  81.     XtDisownSelection(w, global_client.atom, 
  82.               XtLastTimestampProcessed(XtDisplay(w)));
  83.  
  84.     sprintf(msg, "It appears that this client does not understand\n%s",
  85.         "the Editres Protocol.");
  86.     SetMessage(global_screen_data.info_label, msg);
  87. }
  88.  
  89. /*    Function Name: GetClientWindow
  90.  *    Description: Gets the Client's window by asking the user.
  91.  *    Arguments: w - a widget.
  92.  *    Returns: a clients window, or None.
  93.  */
  94.  
  95. Window 
  96. GetClientWindow(w, x, y)
  97. Widget w;
  98. int *x, *y;
  99. {
  100.     int status;
  101.     Cursor cursor;
  102.     XEvent event;
  103.     int buttons = 0;
  104.     Display * dpy = XtDisplayOfObject(w);
  105.     Window target_win = None, root = RootWindowOfScreen(XtScreenOfObject(w));
  106.     XtAppContext app = XtWidgetToApplicationContext(w);
  107.     
  108.     /* Make the target cursor */
  109.     cursor = XCreateFontCursor(dpy, XC_crosshair);
  110.     
  111.     /* Grab the pointer using target cursor, letting it room all over */
  112.     status = XGrabPointer(dpy, root, False,
  113.                ButtonPressMask|ButtonReleaseMask, GrabModeSync,
  114.                GrabModeAsync, root, cursor, CurrentTime);
  115.     if (status != GrabSuccess) {
  116.     SetMessage(global_screen_data.info_label, "Can't grab the mouse.\n");
  117.     return(None);
  118.     }
  119.  
  120.     /* Let the user select a window... */
  121.     while ((target_win == None) || (buttons != 0)) {
  122.     /* allow one more event */
  123.     XAllowEvents(dpy, SyncPointer, CurrentTime);
  124.     XtAppNextEvent(app, &event);
  125.     switch (event.type) {
  126.     case ButtonPress:
  127.         if (event.xbutton.window != root) {
  128.         XtDispatchEvent(&event);
  129.         break;
  130.         }
  131.  
  132.         if (target_win == None) {
  133.         target_win = event.xbutton.subwindow; /* window selected */
  134.         if (x != NULL)
  135.             *x = event.xbutton.x_root;
  136.         if (y != NULL)
  137.             *y = event.xbutton.y_root;
  138.         }
  139.         buttons++;
  140.         break;
  141.     case ButtonRelease:
  142.         if (event.xbutton.window != root) {
  143.         XtDispatchEvent(&event);
  144.         break;
  145.         }
  146.  
  147.         if (buttons > 0) /* There may have been some
  148.                 down before we started */
  149.         buttons--;
  150.         break;
  151.     default:
  152.         XtDispatchEvent(&event);
  153.         break;
  154.     }
  155.     } 
  156.     
  157.     XUngrabPointer(dpy, CurrentTime);      /* Done with pointer */
  158.  
  159.     return(XmuClientWindow(dpy, target_win));
  160. }
  161.  
  162. /*    Function Name: SetCommand
  163.  *    Description: Causes this widget to own the resource editor's 
  164.  *                   command selection.
  165.  *    Arguments: w - the widget that will own the selection.
  166.  *                 command - command to send to client.
  167.  *                 msg - message to prompt the user to select a client.
  168.  *    Returns: none.
  169.  */
  170.  
  171. /* ARGSUSED */
  172. void
  173. SetCommand(w, command, msg)
  174. Widget w;
  175. ResCommand command;
  176. char * msg;
  177. {
  178.     XClientMessageEvent client_event;
  179.     Display * dpy = XtDisplay(w);
  180.     
  181.     if (msg == NULL) 
  182.     msg = "Click the mouse pointer on any Xaw client.";
  183.  
  184.     SetMessage(global_screen_data.info_label, msg);
  185.           
  186.     if (global_client.window == None) {
  187.     if ( (global_client.window = GetClientWindow(w, NULL, NULL)) == None) 
  188.         return;
  189.     }
  190.  
  191.     global_client.ident = GetNewIdent();
  192.     
  193.     global_client.command = command;
  194.     global_client.atom = atom_comm;
  195.  
  196.     BuildHeader(&(global_client)); 
  197.  
  198.     if (!XtOwnSelection(w, global_client.atom, CurrentTime, ConvertCommand, 
  199.             LoseSelection, SelectionDone))
  200.     SetMessage(global_screen_data.info_label,
  201.            "Unable to own the Resource Selection");
  202.  
  203.     client_event.window = global_client.window;
  204.     client_event.type = ClientMessage;
  205.     client_event.message_type = atom_resource_editor;
  206.     client_event.format = EDITRES_SEND_EVENT_FORMAT;
  207.     client_event.data.l[0] = XtLastTimestampProcessed(dpy);
  208.     client_event.data.l[1] = global_client.atom;
  209.     client_event.data.l[2] = (long) global_client.ident;
  210.     client_event.data.l[3] = CURRENT_PROTOCOL_VERSION;
  211.  
  212.     global_error_code = NO_ERROR;                 /* Reset Error code. */
  213.     global_old_error_handler = XSetErrorHandler(HandleXErrors);
  214.     global_serial_num = NextRequest(dpy);
  215.  
  216.     XSendEvent(dpy, global_client.window, FALSE, (long) 0, 
  217.            (XEvent *) &client_event);
  218.  
  219.     XSync(dpy, FALSE);
  220.     XSetErrorHandler(global_old_error_handler);
  221.     if (global_error_code == NO_WINDOW) {
  222.     char error_buf[BUFSIZ];
  223.     
  224.     global_error_code = NO_ERROR;    /* Reset Error code. */
  225.     sprintf(error_buf, "The communication window with%s%s.",
  226.         " application is no longer avaliable\n",
  227.         "Please select the application manually");
  228.  
  229.     global_client.window = None;
  230.     SetCommand(w, command, error_buf);
  231.     return;
  232.     }   
  233.            
  234.     TellUserAboutMessage(global_screen_data.info_label, command);
  235.     global_client.timeout = XtAppAddTimeOut(XtWidgetToApplicationContext(w),
  236.                         CLIENT_TIME_OUT, 
  237.                         ClientTimedOut, (XtPointer) w);
  238. }
  239.  
  240. /*    Function Name: TellUserAboutMessage
  241.  *    Description: Informs the user that we have sent a message to the client
  242.  *    Arguments: label - the info label.
  243.  *                 command - command that we have executed.
  244.  *    Returns: none.
  245.  */
  246.  
  247. static void
  248. TellUserAboutMessage(label, command)
  249. Widget label;
  250. ResCommand command;
  251. {
  252.     char msg[BUFSIZ], *str;
  253.  
  254.     switch(command) {
  255.     case LocalSendWidgetTree:
  256.     str = " asking for widget tree";
  257.     break;
  258.     case LocalSetValues:
  259.     str = " asking it to perform SetValues()";
  260.     break;
  261.     case LocalFlashWidget:
  262.     case LocalGetGeometry:
  263.     str = " asking it to perform GetGeometry()";
  264.     break;
  265.     case LocalGetResources:
  266.     str = " asking it to get a widget's resource list";
  267.     break;
  268.     case LocalFindChild:
  269.     str = " asking it to find the child Widget.";
  270.     break;
  271.     default:
  272.     str = "";
  273.     break;
  274.     }
  275.  
  276.     sprintf(msg, "Message sent to client%s.", str);
  277.     SetMessage(label, msg);
  278. }
  279.  
  280. /*    Function Name: ConvertCommand
  281.  *    Description: Converts the command string into a selection that can
  282.  *                   be sent to the client.
  283.  *    Arguments: (see Xt)
  284.  *    Returns: TRUE if we could convert the selection and target asked for.
  285.  */
  286.  
  287. /* ARGSUSED */
  288. static Boolean
  289. ConvertCommand(w,selection,target,type_ret, value_ret, length_ret, format_ret)
  290. Widget w;
  291. Atom * selection, * target, * type_ret;
  292. XtPointer *value_ret;
  293. unsigned long * length_ret;
  294. int * format_ret;
  295. {
  296.     if ((*selection != atom_comm) || (*target != atom_command))
  297.     return(FALSE);
  298.  
  299.     *type_ret = atom_editres_protocol;
  300.     *value_ret = (XtPointer) global_client.stream.real_top;
  301.     *length_ret = global_client.stream.size + HEADER_SIZE;
  302.     *format_ret = EDITRES_FORMAT;
  303.     
  304.     return(TRUE);
  305. }
  306.  
  307. /*    Function Name: SelectionDone
  308.  *    Description: done with the selection.
  309.  *    Arguments: *** UNUSED ***
  310.  *    Returns: none.
  311.  */
  312.  
  313. /* ARGSUSED */
  314. static void
  315. SelectionDone(w, sel, targ)
  316.     Widget w;
  317.     Atom *sel, *targ;
  318. {
  319.     /* Keep the toolkit from automaticaly freeing the selection value */
  320. }
  321.  
  322. /*    Function Name: LoseSelection
  323.  *    Description: Called when we have lost the selection, asks client
  324.  *                   for the selection value.
  325.  *    Arguments: w - the widget that just lost the selection.
  326.  *                 sel - the selection.
  327.  *    Returns: none.
  328.  */
  329.  
  330. static void
  331. LoseSelection(w, sel)
  332. Widget w;
  333. Atom * sel;
  334. {
  335.     if (global_client.timeout != 0) {
  336.     XtRemoveTimeOut(global_client.timeout);
  337.     global_client.timeout = 0;
  338.     }
  339.  
  340.     XtGetSelectionValue(w, *sel, atom_client_value, GetClientValue,
  341.             NULL, XtLastTimestampProcessed(XtDisplay(w)));
  342. }
  343.  
  344. /*    Function Name: GetClientValue
  345.  *    Description: Gets the value out of the client, and does good things
  346.  *                   to it.
  347.  *    Arguments: w - the widget that asked for the selection.
  348.  *                 data - client_data *** UNUSED ***.
  349.  *                 sel - the selection.
  350.  *                 type - the type of the selection.
  351.  *                 value - the selection's value.
  352.  *                 length - the length of the selection's value.
  353.  *                 format - the format of the selection.
  354.  *    Returns: none.
  355.  */
  356.  
  357.  
  358. /* ARGSUSED */
  359. static void
  360. GetClientValue(w, data, selection, type, value, length, format)
  361. Widget w;
  362. XtPointer data, value;
  363. Atom *selection, *type;
  364. unsigned long *length;
  365. int * format;
  366. {
  367.     Event * event;
  368.     ProtocolStream alloc_stream, *stream;
  369.     unsigned char ident, error_code;
  370.     char * error_str, msg[BUFSIZ];
  371.  
  372.     if (*length == 0)
  373.     return;
  374.  
  375.     stream = &alloc_stream;    /* easier to think of it this way... */
  376.  
  377.     stream->current = stream->top = (unsigned char *) value;
  378.     stream->size = HEADER_SIZE;        /* size of header. */
  379.  
  380.     /*
  381.      * Retrieve the Header.
  382.      */
  383.  
  384.     if (*length < HEADER_SIZE) {
  385.     SetMessage(global_screen_data.info_label,
  386.            "Incorrectly formatted message from client.");
  387.     return;
  388.     }
  389.  
  390.     (void) _XEditResGet8(stream, &ident);
  391.     if (global_client.ident != ident) {
  392. #ifdef DEBUG
  393.     if (global_resources.debug)
  394.         printf("Incorrect ident from client.\n");
  395. #endif 
  396.     if (!XtOwnSelection(w, *selection, CurrentTime, ConvertCommand, 
  397.                 LoseSelection, SelectionDone))
  398.         SetMessage(global_screen_data.info_label,
  399.                "Unable to own the Resource Editor Command Selection");
  400.     return;
  401.     }
  402.  
  403.     (void) _XEditResGet8(stream, &error_code); 
  404.     (void) _XEditResGet32(stream, &(stream->size));
  405.     stream->top = stream->current; /* reset stream to top of value.*/
  406.  
  407.     switch ((int) error_code) {
  408.     case PartialSuccess:
  409.     if ((event = BuildEvent(stream)) != NULL) {
  410.         error_str = DispatchEvent(event);
  411.         FreeEvent(event);
  412.     }
  413.     else {
  414.         sprintf(msg, "Unable to unpack protocol request.");
  415.         error_str = XtNewString(msg);
  416.     }
  417.     break;
  418.     case Failure:
  419.     error_str = GetFailureMessage(stream);
  420.     break;
  421.     case ProtocolMismatch:
  422.     error_str = ProtocolFailure(stream);
  423.     break;
  424.     default:
  425.     sprintf(msg, "Unknown Error code %d", (int) error_code);
  426.     SetMessage(global_screen_data.info_label, msg);
  427.     break;
  428.     }
  429.  
  430.     if (error_str == NULL) {
  431.     WNode * top;
  432.     
  433.     if (global_tree_info == NULL)
  434.         return;
  435.     
  436.     top = global_tree_info->top_node;
  437.     sprintf(msg, "Widget Tree for client %s(%s).", top->name, top->class);
  438.     SetMessage(global_screen_data.info_label, msg);
  439.     return;
  440.     }
  441.     SetMessage(global_screen_data.info_label, error_str);
  442.     XtFree(error_str);
  443. }
  444.  
  445. /*    Function Name: BuildHeader
  446.  *    Description: Puts the header into the message.
  447.  *    Arguments: client_data - the client data.
  448.  *    Returns: none.
  449.  */
  450.  
  451. static void
  452. BuildHeader(client_data)
  453. CurrentClient * client_data;
  454. {
  455.     unsigned long old_alloc, old_size;
  456.     unsigned char * old_current;
  457.     EditresCommand command;
  458.     ProtocolStream * stream = &(client_data->stream);
  459.  
  460.     /*
  461.      * We have cleverly keep enough space at the top of the header
  462.      * for the return protocol stream, so all we have to do is
  463.      * fill in the space.
  464.      */
  465.  
  466.     /* 
  467.      * Fool the insert routines into putting the header in the right
  468.      * place while being damn sure not to realloc (that would be very bad.
  469.      */
  470.     
  471.     old_current = stream->current;
  472.     old_alloc = stream->alloc;
  473.     old_size = stream->size;
  474.  
  475.     stream->current = stream->real_top;
  476.     stream->alloc = stream->size + (2 * HEADER_SIZE);    
  477.     
  478.     _XEditResPut8(stream, client_data->ident);
  479.     switch(client_data->command) {
  480.     case LocalSendWidgetTree:
  481.     command = SendWidgetTree;
  482.     break;
  483.     case LocalSetValues:
  484.     command = SetValues;
  485.     break;
  486.     case LocalFlashWidget:
  487.     command = GetGeometry;
  488.     break;
  489.     case LocalGetResources:
  490.     command = GetResources;
  491.     break;
  492.     case LocalFindChild:
  493.     command = FindChild;
  494.     break;
  495.     default:
  496.     command = SendWidgetTree;
  497.     break;
  498.     }
  499.                   
  500.     _XEditResPut8(stream, (unsigned char) command);
  501.     _XEditResPut32(stream, old_size);
  502.  
  503.     stream->alloc = old_alloc;
  504.     stream->current = old_current;
  505.     stream->size = old_size;
  506. }
  507.  
  508. /*    Function Name: BuildEvent
  509.  *    Description: Builds the event structure from the 
  510.  *    Arguments: stream - the protocol data stream.
  511.  *    Returns: event - the event.
  512.  */
  513.  
  514. static Event * 
  515. BuildEvent(stream)
  516. ProtocolStream * stream;
  517. {
  518.     int i;
  519.     Event * event = (Event *) XtCalloc(sizeof(Event), 1);
  520.  
  521.     /*
  522.      * The return value will be different depending upon the
  523.      * request sent out.
  524.      */
  525.  
  526.     switch(global_client.command) {
  527.     case LocalSendWidgetTree:
  528.         {
  529.         SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event;
  530.  
  531.         send_event->type = SendWidgetTree;
  532.  
  533.         if (!_XEditResGet16(stream, &(send_event->num_entries)))
  534.         goto done;
  535.         
  536.         send_event->info = (WidgetTreeInfo *)
  537.                         XtCalloc(sizeof(WidgetTreeInfo),
  538.                      send_event->num_entries);
  539.  
  540.         for (i = 0; i < (int)send_event->num_entries; i++) {
  541.         WidgetTreeInfo * info = send_event->info + i;
  542.         if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) &&
  543.               _XEditResGetString8(stream, &(info->name)) &&
  544.               _XEditResGetString8(stream, &(info->class)) &&
  545.               _XEditResGet32(stream, &(info->window)))) 
  546.         {
  547.             goto done;
  548.         }
  549.         }
  550.     }
  551.     break;
  552.     case LocalSetValues:
  553.         {
  554.         SetValuesEvent * sv_event = (SetValuesEvent *) event;
  555.  
  556.         sv_event->type = SetValues;
  557.  
  558.         if (!_XEditResGet16(stream, &(sv_event->num_entries)))
  559.         goto done;
  560.         
  561.         sv_event->info = (SetValuesInfo *) XtCalloc(sizeof(SetValuesInfo),
  562.                             sv_event->num_entries);
  563.  
  564.         for (i = 0; i < (int)sv_event->num_entries; i++) {
  565.         SetValuesInfo * info = sv_event->info + i;
  566.         if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) &&
  567.               _XEditResGetString8(stream, &(info->message))))
  568.         {
  569.             goto done;
  570.         }
  571.         }
  572.     }
  573.     break;
  574.     case LocalGetResources:
  575.         {
  576.         GetResourcesEvent * res_event = (GetResourcesEvent *) event;
  577.         
  578.         res_event->type = GetGeometry;
  579.  
  580.         if (!_XEditResGet16(stream, &(res_event->num_entries)))
  581.         goto done;
  582.  
  583.         res_event->info = (GetResourcesInfo *) 
  584.                            XtCalloc(sizeof(GetResourcesInfo),
  585.                         res_event->num_entries);
  586.  
  587.         for (i = 0; i < (int)res_event->num_entries; i++) {
  588.         GetResourcesInfo * res_info = res_event->info + i;
  589.         if (!(_XEditResGetWidgetInfo(stream, &(res_info->widgets)) &&
  590.               _XEditResGetBoolean(stream, &(res_info->error))))
  591.         {
  592.             goto done;
  593.         }
  594.         if (res_info->error) {
  595.             if (!_XEditResGetString8(stream, &(res_info->message))) 
  596.             goto done;
  597.         }
  598.         else {
  599.             unsigned int j;
  600.  
  601.             if (!_XEditResGet16(stream, &(res_info->num_resources)))
  602.             goto done;
  603.  
  604.             res_info->res_info = (ResourceInfo *) 
  605.                               XtCalloc(sizeof(ResourceInfo),
  606.                            res_info->num_resources);
  607.  
  608.             for (j = 0; j < res_info->num_resources; j++) {
  609.             unsigned char temp;
  610.             ResourceInfo * info = res_info->res_info + j;
  611.             if (!(_XEditResGetResType(stream, &(temp)) &&
  612.                   _XEditResGetString8(stream, &(info->name)) &&
  613.                   _XEditResGetString8(stream, &(info->class)) &&
  614.                   _XEditResGetString8(stream, &(info->type))))
  615.             {
  616.                 goto done;
  617.             }
  618.             else
  619.                 info->res_type = (ResourceType) temp;
  620.             } /* for */
  621.         } /* else */
  622.         } /* for */
  623.     }
  624.     break;
  625.     case LocalFlashWidget:
  626.     case LocalGetGeometry:
  627.         {
  628.         GetGeomEvent * geom_event = (GetGeomEvent *) event;
  629.  
  630.         geom_event->type = GetGeometry;
  631.  
  632.         if (!_XEditResGet16(stream, &(geom_event->num_entries)))
  633.         goto done;
  634.         
  635.         geom_event->info = (GetGeomInfo *) XtCalloc(sizeof(GetGeomInfo),
  636.                               geom_event->num_entries);
  637.  
  638.         for (i = 0; i < (int)geom_event->num_entries; i++) {
  639.         GetGeomInfo * info = geom_event->info + i;
  640.         if (!(_XEditResGetWidgetInfo(stream, &(info->widgets)) &&
  641.               _XEditResGetBoolean(stream, &(info->error))))
  642.         {
  643.             goto done;
  644.         }
  645.         if (info->error) {
  646.             if (!_XEditResGetString8(stream, &(info->message)))
  647.             goto done;
  648.         }
  649.         else {
  650.             if (!(_XEditResGetBoolean(stream, &(info->visable)) &&
  651.               _XEditResGetSigned16(stream, &(info->x)) &&
  652.               _XEditResGetSigned16(stream, &(info->y)) &&
  653.               _XEditResGet16(stream, &(info->width)) &&
  654.               _XEditResGet16(stream, &(info->height)) &&
  655.               _XEditResGet16(stream, &(info->border_width))))
  656.             {
  657.             goto done;
  658.             }
  659.         }
  660.         }
  661.     }
  662.     break;
  663.     case LocalFindChild:
  664.         {
  665.         FindChildEvent * find_event = (FindChildEvent *) event;
  666.  
  667.         find_event->type = FindChild;
  668.  
  669.         if (!_XEditResGetWidgetInfo(stream, &(find_event->widgets)))
  670.         goto done;
  671.     }
  672.     break;
  673.     default:
  674.     goto done;
  675.     }
  676.  
  677.     return(event);
  678.  
  679.  done:
  680.     FreeEvent(event);
  681.     return(NULL);
  682. }
  683.  
  684.  
  685. /*    Function Name: FreeEvent
  686.  *    Description: Frees all memory associated with the event. 
  687.  *    Arguments: event - the event.
  688.  *    Returns: none.
  689.  *
  690.  * NOTE: XtFree() returns w/o freeing if ptr is NULL.
  691.  */
  692.  
  693. static void
  694. FreeEvent(event)
  695. Event * event;
  696. {
  697.     unsigned int i;
  698.  
  699.     switch(event->any_event.type) {
  700.     case SendWidgetTree:
  701.         {
  702.         SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event;
  703.         WidgetTreeInfo * info = send_event->info;
  704.         
  705.         if (info != NULL) {
  706.         for (i = 0; i < send_event->num_entries; i++, info++) {
  707.             XtFree((char *)info->widgets.ids);
  708.             XtFree(info->name);
  709.             XtFree(info->class);
  710.         }
  711.         XtFree((char *)send_event->info);
  712.         }
  713.     }
  714.     break;
  715.     case SetValues:
  716.         {
  717.         SetValuesEvent * sv_event = (SetValuesEvent *) event;
  718.         SetValuesInfo * info = sv_event->info;
  719.         
  720.         if (info != NULL) {
  721.         for (i = 0; i < sv_event->num_entries; i++, info++) {
  722.             XtFree((char *)info->widgets.ids);
  723.             XtFree(info->message);
  724.         }
  725.         XtFree((char *)sv_event->info);
  726.         }
  727.     }
  728.     break;
  729.     case GetResources:
  730.         {
  731.         GetResourcesEvent * get_event = (GetResourcesEvent *) event;
  732.         GetResourcesInfo * info = get_event->info;
  733.  
  734.         if (info != NULL) {
  735.         for (i = 0; i < get_event->num_entries; i++, info++) {
  736.             XtFree((char *)info->widgets.ids);
  737.             if (info->error) 
  738.             XtFree(info->message);
  739.             else {
  740.             unsigned int j;
  741.             ResourceInfo * res_info = info->res_info;
  742.             
  743.             if (res_info != NULL) {
  744.                 for (j = 0; 
  745.                  j < info->num_resources; j++, res_info++) 
  746.                 {
  747.                 XtFree(res_info->name);
  748.                 XtFree(res_info->class);
  749.                 XtFree(res_info->type);
  750.                 }
  751.                 XtFree((char *)info->res_info);
  752.             }
  753.             }
  754.         } 
  755.         XtFree((char *)get_event->info);
  756.         }
  757.     }
  758.     break;
  759.     case GetGeometry:
  760.         {
  761.         GetGeomEvent * geom_event = (GetGeomEvent *) event;
  762.         GetGeomInfo * info = geom_event->info;
  763.  
  764.         if (info != NULL) {
  765.         for (i = 0; i < geom_event->num_entries; i++, info++) {
  766.             XtFree((char *)info->widgets.ids);
  767.             if (info->error) 
  768.             XtFree(info->message);
  769.         }
  770.         XtFree((char *)geom_event->info);
  771.         }
  772.     }
  773.     break;
  774.     case FindChild:
  775.         {
  776.         FindChildEvent * find_event = (FindChildEvent *) event;
  777.         
  778.         XtFree((char *)find_event->widgets.ids);
  779.     }
  780.     break;
  781.     default:
  782.     break;
  783.     }
  784. }
  785.  
  786. /*    Function Name: DispatchEvent
  787.  *    Description: Handles the event, calling the proper function.
  788.  *    Arguments: event - the event.
  789.  *    Returns: one.
  790.  */
  791.     
  792. static char *
  793. DispatchEvent(event)
  794. Event * event;
  795. {
  796.     char * error = NULL;
  797.  
  798.     switch(global_client.command) {
  799.     case LocalSendWidgetTree:
  800.     BuildVisualTree(global_tree_parent, event);
  801.     break;
  802.     case LocalSetValues:
  803.     error = PrintSetValuesError(event);
  804.     break;
  805.     case LocalFlashWidget:
  806.     error = HandleFlashWidget(event);
  807.     break;
  808.     case LocalGetResources:
  809.     error = HandleGetResources(event);
  810.     break;
  811.     case LocalFindChild:
  812.     DisplayChild(event);
  813.     break;
  814.     default:
  815.         {
  816.         char msg[BUFSIZ];
  817.         sprintf(msg, "Internal error: Unknown command %d.", 
  818.             global_client.command);
  819.         error = XtNewString(msg);
  820.     }
  821.     break;
  822.     }
  823.     return(error);
  824. }
  825.  
  826. /*    Function Name: InternAtoms
  827.  *    Description: interns all static atoms.
  828.  *    Arguments: display - the current display.
  829.  *    Returns: none.
  830.  */
  831.  
  832. void
  833. InternAtoms(dpy)
  834. Display * dpy;
  835. {
  836.     atom_comm = XInternAtom(dpy, EDITRES_COMM_ATOM, False);
  837.     atom_command = XInternAtom(dpy, EDITRES_COMMAND_ATOM, False);
  838.     atom_resource_editor = XInternAtom(dpy, EDITRES_NAME, False);
  839.     atom_client_value = XInternAtom(dpy, EDITRES_CLIENT_VALUE, False);
  840.     atom_editres_protocol = XInternAtom(dpy, EDITRES_PROTOCOL_ATOM, False);
  841. }
  842.  
  843. ResIdent
  844. GetNewIdent()
  845. {
  846.     static ResIdent ident = 1;
  847.  
  848.     return(ident++);
  849. }
  850.  
  851.